
package core
import scala.collection.mutable.ArrayBuffer
import scala.swing._
import event._
import java.awt.Color
import core.ScalaCheckers.Point
import scala.util.matching.Regex

object ScalaCheckers {
		/**Constant representing an empty space.*/
		val EMPTY = 0
		/**Constant representing a light single man.*/
		val LIGHT = 1
		/**Constant representing a light king.*/
		val LIGHT_KING = 2
		/**Constant representing a dark single man.*/
		val DARK = 3
		/**Constant representing a dark king.*/
		val DARK_KING = 4
		/** Constant representing a standard sized board. */
		val STD_BOARD_SIZE = 8
		/** Change to true to activate debug code: */
		val debug = false
		/** Array used for the board positions: */
		var iBoard = new Array[Array[Int]](STD_BOARD_SIZE)
		/** Boolean to control the turn structure: */
		var iDarkPlayerTurn = false
		/** Conversion array for columns A-H */
		val colConversionArray = List ("A","B","C","D","E","F","G","H")
		/** User Quit boolean, set in readConsole() function */
		var userQuit = false
		
		
		//Main method which allows user to play via using console input/output (No GUI)
		def main(args:Array[String]) = {
			//Start game by initializing board			
			println("Game starting....")
			init
			println("Fresh board created!")
			
			// while game is still not won and userQuit has not been set (by typing Quit), the game continues
			while (gameHasBeenWon == 0 && !userQuit){
				//print the board to the console
				printBoard
			
				//inform user of turn
				if (isDarkPlayerTurn){
					println("Dark Player Turn")
				}
				else {
					println("Light Player turn")
				}
				readConsole
			}
			
			//if game won, then print congrats message and exit
			if (gameHasBeenWon != 0) {
				printBoard
				gameHasBeenWon match {
					case 1 => println("Congratulations Dark Team!")
					case 2 => println("Congratulations Light Team!")
					case _ => println("Error!")
				}
				exit
			} 
		}		

		
		/**Reads the user input from the console and validates that it's in 
		   [A-H][1-8] [A-H][1-8] format to parse, then calls makeMove if it is correct
	       @return If user enters valid board positions, calls makeMove. If user enters 'Quit', exists
	       the game, Otherwise, it gives an error message to the user to try again.
		*/
		def readConsole{
			println("Type \"Quit\" if you would like to end the game")
			println("Enter position to move from and to in \"[A-H][1-8] [A-H][1-8]\" format:")
			val positionParser = "([A-H])([1-8]) ([A-H])([1-8])".r
			val s = Console.readLine
		
			s.toUpperCase match {
				// check user entered position in (Col1, Row1, Col2, Row2) format
				case positionParser(cy1, cx1, cy2, cx2) => {
						print("You entered to move from ")
						printf("Col:%s Row:%s to Col:%s Row:%s", cy1, cx1, cy2, cx2)
						println
						
						// convert user entered X values to int
						val x1 = cx1.toInt
						val x2 = cx2.toInt
						
						// lookup the user entered values for Y and find their respective position in colConversionArray
						val y1 = colConversionArray.indexOf(cy1)+1
						val y2 = colConversionArray.indexOf(cy2)+1
						
						makeMove(y1, x1, y2, x2)
				}
				
				// If user enters 'quit' (case insensitive), then sets the userQuit flag to true and prints message
				case "QUIT" => {
					userQuit = true
					println("Thanks for playing Scala Checkers!")
				}
				
				// Catch all non-matching entries
				case _ => println ("Incorrect position, try again")
			}
		}
		
		
		/*** Move Debug Message to print out debug statements
		 * @param x The horizontal component of the coordinate
		 * @param y The vertical component of the coordinate
		 * @param msg The message you want to display
		 */
		
		def moveDebugMsg(x:Int, y:Int, msg:String){
			if (debug)
				println(" (" + x + ", " + y + ") " + msg + ".")
		}
		
		
	/**Determines whether a piece at the specified coordinate is capable of
	   a single jump. This method does not take into account whether the move
	   is allowed by the current turn state. It checks only if the move is possible
	   with the current rule set and board state.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has a jump move available.
	   False if otherwise.
	*/
		
	def canJump(x:Int, y:Int): Boolean={
		if (isEmpty(x, y) || isIllegalSpace(x, y)) {
			moveDebugMsg(x ,y, "cannot jump: Space is illegal or empty")
			return false;
		} else if (isDark(x, y)) {
			if (isLight(x + 1, y + 1) && isEmpty(x + 2, y + 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}

			if (isLight(x - 1, y + 1) && isEmpty(x - 2, y + 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}

			if (isKing(x, y)
				&& isLight(x + 1, y - 1)
				&& isEmpty(x + 2, y - 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}

			if (isKing(x, y)
				&& isLight(x - 1, y - 1)
				&& isEmpty(x - 2, y - 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}

			moveDebugMsg(x ,y, "cannot jump: No jump available")
			return false
		} else if (isLight(x, y)) {
			if (isDark(x + 1, y - 1) && isEmpty(x + 2, y - 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}
			if (isDark(x - 1, y - 1) && isEmpty(x - 2, y - 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}
			if (isKing(x, y)
				&& isDark(x + 1, y + 1)
				&& isEmpty(x + 2, y + 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}
			if (isKing(x, y)
				&& isDark(x - 1, y + 1)
				&& isEmpty(x - 2, y + 2)) {
				moveDebugMsg(x ,y, "can jump")
				return true
			}

			moveDebugMsg(x ,y, "cannot jump: No jump available")
			return false
		}
		return false
	}
	
	/**Determines whether a piece at the specified board coordinate is
	   capable of simple movement, excluding jumps. This method does
	   not take into account whether this move is allowed by the current
	   turn, e.g. it will not return false if a dark piece is checked
	   on the light player's turn. In other words, it checks only if a
	   move is possible with the current rule set and board state,
	   not the current turn state.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has a possible slide move.
	   False if otherwise.
	*/
	def canSlide(x:Int, y:Int): Boolean={
			if (isEmpty(x, y) || isIllegalSpace(x, y)) {
			moveDebugMsg(x ,y, "cannot slide: Space is illegal or empty")
			return false
		}

		//Dark men move down, light men move up. Kings move in either direction.
		else if (
			(isDark(x, y) || isKing(x, y))
				&& (isEmpty(x + 1, y + 1) || isEmpty(x - 1, y + 1))) {
			moveDebugMsg(x ,y, "can slide")
			return true
		} else if (
			(isLight(x, y) || isKing(x, y))
				&& (isEmpty(x + 1, y - 1) || isEmpty(x - 1, y - 1))) {
			moveDebugMsg(x ,y, "can slide")
			return true
		}

		moveDebugMsg(x ,y, "cannot slide: No slide available")
		return false
	}
	
	/**Determines whether a piece at the specified board coordinate is capable
	   of either moving or jumping. This method does not take into account
	   whether the move is allowed by the current turn state. It checks only
	   whether the move is allowed by the current rule set and board state.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate has either a
	   slide or jump move available. False if otherwise.
	*/
	def canMove (x:Int, y:Int): Boolean={
		return (canSlide(x, y) || canJump(x, y))
	}
	
	/**Checks whether the board is in a win state. A win state exists when
	  one side is unable to move, either due to being blocked by the other
	  player or by having no pieces left.
	  @return - 0 if the game is not in a win state.
	  <br>- 1 if the dark player has won.
	  <br>- 2 if the light player has won.
	*/
	def gameHasBeenWon: Int={
		if (iDarkPlayerTurn) {
			if (!darkCanMove)
				return 2
			return 0
		} else {
			if (!lightCanMove)
				return 1
			return 0
		}
	}
	
	/**Retrieves the size of the board. The board size is measured as the number
	   of squares down one side of the board.
	   @return The size of the board.
	*/
	def getBoardSize(): Int= {
		return STD_BOARD_SIZE
	}
	
		/**Determines whether the piece at board coordinate (x, y) is dark.
	   If the coordinates do not exist on the board or are empty,
	   this method will return false.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is light.
	   False if otherwise.
	*/
	def isDark(x:Int, y:Int): Boolean = {
		try {
			return (
				iBoard(x - 1)(y - 1) == DARK
					|| iBoard(x - 1)(y - 1) == DARK_KING)
		} catch {
			case e:Exception => return false
		}
	}

	/**Determines whose turn it is.
	   @return True if the dark player is to play next. False if otherwise.*/
	def isDarkPlayerTurn(): Boolean = {
		return iDarkPlayerTurn
	}

	/**Switches the turn from the current player to their opponent.
	   This method is called automatically when a turn comes to an end,
	   and is provided as public for use by the game core class only if necessary.
	*/
	def switchPlayerTurn() ={
		iDarkPlayerTurn = !iDarkPlayerTurn
		if (debug) {
			if (isLightPlayerTurn())
				println("Light player turn.")
			else
				println("Dark player turn.")
		}
	}

	/**Determines whose turn it is.
	   @return True if the light player is to play next. False if otherwise.
	*/
	def isLightPlayerTurn(): Boolean = {
		return !iDarkPlayerTurn
	}

	/**Determines whether the piece at board coordinate (x, y) is light.
	   If the coordinates do not exist on the board or are empty,
	   this method will return false.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is light.
	   False if otherwise.
	*/
	def isLight(x:Int, y:Int): Boolean = {
		try {
			return (
				iBoard(x - 1)(y - 1) == LIGHT
					|| iBoard(x - 1)(y - 1) == LIGHT_KING)
		} catch{
			case e:Exception => return false
		}
	}

	/**Determines whether the piece at board coordinate (x, y) is a king.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is a king.
	   False if otherwise.
	*/
	def isKing(x:Int, y:Int): Boolean = {
		try {
			return (
				iBoard(x - 1)(y - 1) == DARK_KING
					|| iBoard(x - 1)(y - 1) == LIGHT_KING)
		} catch{
			case e:Exception=> return false
		}
	}

	/**Determines whether the piece as board coordinate (x, y) is a single man.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the piece at the specified coordinate is a man
	   (i.e. not a king). False if otherwise.
	*/
	def isMan(x:Int, y:Int): Boolean = {
		try {
			return (
				iBoard(x - 1)(y - 1) == DARK || iBoard(x - 1)(y - 1) == LIGHT)
		} catch{
			case e: Exception => return false
		}
	}

	/**Determines whether the board coordinate (x, y) is vacant.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate does not contain a piece.
	   False if otherwise.
	*/
	def isEmpty(x:Int, y:Int): Boolean = {
		try {
			return (iBoard(x - 1)(y - 1) == EMPTY)
		} catch{
			case e: Exception => return false
		}
	}

	/**Determines whether the board coordinate (x, y) contains a piece.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate contains a piece.
	   False if otherwise.
	*/
	def isOccupied(x:Int, y:Int): Boolean = {
		try {
			return (iBoard(x-1)(y-1) != EMPTY)
		} catch{
			case e: Exception => return false
		}
	}
	
	/**Provides a reference to a 2 dimensional array representation
	   of the current board state. This is for use by the user interface. Each dimension
	   of the array extends from 0 to boardsize-1. Therefore a piece at position
	   (x, y) on the board will be represented as a GameEngine constant at
	   array[x-1][y-1]. Note that the referenced array is a clone of the internal
	   board representation. Changes made to the array will not affect the board state.
	  @return A 2 dimensional array representing the current state of the board.
	 */
	def getBoardState: Array[Array[Int]] ={
		return iBoard
	}
	
	/**Initializes the board for a new game.
	   The dark player is set as the first to move.
	*/
	 def init ={
		 for (i <- (0 to STD_BOARD_SIZE - 1)) {
				iBoard(i) = new Array[Int](STD_BOARD_SIZE)
			}
		for (y <- 0 until STD_BOARD_SIZE){
			for( x <- 0 until STD_BOARD_SIZE){
				if (x % 2 == y % 2) {
					//Place dark pieces at the top:
					if (y < 3){
						iBoard(x)(y) = DARK
					}

					//Place light pieces at the bottom:
					if (y > 4){
						iBoard(x)(y) = LIGHT
					}

				} else{
					iBoard(x)(y) = EMPTY
				}
			}
		}
		iDarkPlayerTurn = true
	}
	 
	 /**Creates a string to represent the board state.
	   This string is formatted for use as a simple board display
	   in the console window.
	*/
	 def printBoard = {
		var tOutput = "\n   A  B  C  D  E  F  G  H  \n" 
		// 2010-11-01 EA: Changed columns from numbers to letters in order to be more consistent with a chess board and to be able to clearly define the spaces
		var tRow = 0
		for (y <- 0 until STD_BOARD_SIZE){
			tOutput += tRow + 1 + "  "
			tRow = tRow + 1
			for (x <- 0 until STD_BOARD_SIZE){
				 def matchTest(x: Int): String = x match {
				 	case LIGHT => "LL "
				 	case LIGHT_KING => "LK "
				 	case DARK => "DD "
				 	case DARK_KING => "DK "
				 	case _ => "-- "
				 }
				 tOutput += matchTest(iBoard(x)(y))
				if (x == (STD_BOARD_SIZE - 1)){
					tOutput += "\n"
				}
			}
			// 2010-11-21 EA: Compacted board on command line to make it easier to read without extra spaces
			//tOutput += "\n"
		}
		tOutput += "   A  B  C  D  E  F  G  H  \n"
		println(tOutput)
		
	 }
	 
	 /**Method used to perform a move on the board. A move can only be made
	   successfully if the supplied coordinates are legal and indicate a
	   legal move in the context of the current RuleSet. If the rules specify
	   that a jump must be made if one is possible, then the move will only
	   be made if the coordinates of the piece to be moved are contained
	   within the List object retrieved by the mustJump method, and only if
	   the move made is a jump. Note that all multiple jump moves are made by
	   calling makeMove for every individual jump segment. If a multiple jump
	   sequence has not been completed but the rules state that it must be,
	   the turn will not pass to the opposing player until the sequence is
	   complete. In this case, the List returned by mustJump will contain
	   only the coordinates of the piece that must continue to jump. Also,
	   a move can only be made if the piece to be moved belongs to the player
	   whose turn it is.
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be moved.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be moved.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the move has been successfully made.
	   False if otherwise.
	*/
	def makeMove(x1:Int, y1:Int, x2:Int, y2:Int): Boolean = {
		if (debug){
			println(
				"makeMove executing ("
					+ x1
					+ ", "
					+ y1
					+ ") to ("
					+ x2
					+ ", "
					+ y2
					+ ")...")
		}
		
		//Check that the first coordinate is valid, and refers to a piece of the correct colour:
		if (isIllegalSpace(x1, y1)
			|| isEmpty(x1, y1)
			|| (isLight(x1, y1) && isDarkPlayerTurn())
			|| (isDark(x1, y1) && isLightPlayerTurn())) {
			if (debug){
				println(
					"Move from  ("
						+ x1
						+ ", "
						+ y1
						+ ") to ("
						+ x2
						+ ", "
						+ y2
						+ ") has failed.")
			}
			return false
		}
		//The piece to be moved is valid. Retrieve the list of all pieces that must jump:
		val tJumpList = mustJump

		//If this list is non-empty then a piece must jump. Check that the specified piece
		//is contained on the list:
		if (tJumpList.size > 0) {
			var tFlag = false
			var break = false
			for (i <- (0 to tJumpList.size - 1)) {
				if(!break){
					var tPoint = tJumpList(i);
					if (x1 == tPoint.getX() && y1 == tPoint.getY()) {
						if (debug){
							println(
								" Piece to be moved is contained on the jump list.");
						}
						tFlag = true
						break = true
					}
				}
			}

			if (!tFlag) {
				if (debug){
					println(
						"Move from  ("
							+ x1
							+ ", "
							+ y1
							+ ") to ("
							+ x2
							+ ", "
							+ y2
							+ ") has failed: another piece on the board must jump.")
				}
				return false
			}

			//The piece is on the list. Check that the move to be made is a legal jump.
			if (!isLegalJump(x1, y1, x2, y2)) {
				if (debug){
					println(
						"Move from  ("
							+ x1
							+ ", "
							+ y1
							+ ") to ("
							+ x2
							+ ", "
							+ y2
							+ ") has failed: Not a legal move.")
				}
				return false
			}

			if (debug){
				println("Jump called from makeMove.")
			}
			//The move is legal and contained on the list. Make it:
			jump(x1, y1, x2, y2)
			//If the piece now has a jump move accessible to it, the turn has not ended:
			if (canJump(x2, y2)) {
				//In US rules, a piece with a move in progress cannot be in a position to be
				//crowned.
				if (debug){
					println("makeMove Successful!\n" + this +" \n")
				}
				return true
			} else {
				//Will only crown the piece if it is in the correct location:
				crown(x2, y2)
				if (debug){
					println("makeMove Successful!\n" + this +" \n")
				}
				switchPlayerTurn
				return true
			}

		}

		//If the list is empty then there are no possible jumps, and the move must be a slide. Check for a legal slide move:
		else if (isLegalSlide(x1, y1, x2, y2)) {
			//The move is legal. Make it:
			slide(x1, y1, x2, y2)
			//Will only crown the piece if it is in the correct location:
			crown(x2, y2)
			if (debug){
				println(
					"makeMove (slide) Successful!\n" + this +"\n")
			}
			switchPlayerTurn
			return true
		}
		if (debug){
			println(
				"Move from  ("
					+ x1
					+ ", "
					+ y1
					+ ") to ("
					+ x2
					+ ", "
					+ y2
					+ ") has failed: UNKNOWN ERROR!")
		}
		return false
	}

	/**Determines whether the board coordinate (x, y) is used in the game.
	   In most cases, all light spaces on the board will be considered illegal.
	   Also, any coordinate which does not exist is also considered illegal.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate is nonexistant or unused in
	   the current rules. False if otherwise.
	*/

	def isIllegalSpace(x:Int, y:Int): Boolean = {
			return (
			x < 1
				|| x > STD_BOARD_SIZE
				|| y < 1
				|| y > STD_BOARD_SIZE
				|| (x - 1) % 2 != (y - 1) % 2)
	}

	/**Determines whether the board coordinate (x, y) is legally used in
	   the game.
	   @param x The horizontal component of the coordinate.
	   @param y The vertical component of the coordinate.
	   @return True if the specified coordinate is legal in the context of
	   the current rules. False if otherwise.
	*/
	def isLegalSpace(x:Int, y:Int): Boolean = {
		return !isIllegalSpace(x, y)
	}

	/**Determines whether a move from (x1, y1) to (x2, y2) is a legal slide.
	   Does not take into account the current turn state.
	   @param x1 The horizontal component of the coordinates containing
	   the piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified slide is legal within the current rules.
	   False if otherwise.
	 */
	def isLegalSlide(x1:Int, y1:Int, x2:Int, y2:Int): Boolean = {
		if (isIllegalSpace(x1, y1) || isIllegalSpace(x2, y2)){
			return false
		}
		if (isEmpty(x1, y1) || isOccupied(x2, y2)){
			return false
		}
		if (isDark(x1, y1) || isKing(x1, y1)) {
			if (Math.abs(x2 - x1) == 1 && y2 == y1 + 1){
				return true
			}
		}
		if (isLight(x1, y1) || isKing(x1, y1)) {
			if (Math.abs(x2 - x1) == 1 && y2 == y1 - 1){
				return true
			}
		}
		return false

	}

	/**Determines whether a move from (x1, y1) to (x2, y2) is a legal jump.
	   Does not take into account the current turn state.
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified single jump is legal within the current rules.
	   False if otherwise.
	*/
	def isLegalJump(x1:Int, y1:Int, x2:Int, y2:Int): Boolean = {
		if (isIllegalSpace(x1, y1) || isIllegalSpace(x2, y2)){
			return false
		}
		if (isEmpty(x1, y1) || isOccupied(x2, y2)){
			return false
		}
		if (Math.abs(x2 - x1) != 2 || Math.abs(y2 - y1) != 2){
			return false
		}
		//If statements to work out which of 4 directions the jump is being made, and
		//if a piece of the right type exists to be jumped.
		val tTempX = x2 - x1
		val tTempY = y2 - y1
		//each value is either 2 or -2, indicating direction.
		if (tTempX == 2) {
			if (tTempY == 2) {
				//Check that the space between the coordinates is occupied.
				//Check that the occupying piece is a different colour to the jumping piece.
				//If these conditions are met, return true.
				if (isEmpty(x1 + 1, y1 + 1)
					|| isSameColour(x1, y1, x1 + 1, y1 + 1)){
					return false
				}
				else{
					return true
				}
			} else {
				if (isEmpty(x1 + 1, y1 - 1)
					|| isSameColour(x1, y1, x1 + 1, y1 - 1)){
					return false
				}
				else{
					return true
				}
			}
		}
		//Else -2:
		else {
			if (tTempY == 2) {
				if (isEmpty(x1 - 1, y1 + 1)
					|| isSameColour(x1, y1, x1 - 1, y1 + 1)){
					return false
				}
				else{
					return true
				}
			} else {
				if (isEmpty(x1 - 1, y1 - 1)
					|| isSameColour(x1, y1, x1 - 1, y1 - 1)){
					return false
				}
				else{
					return true
				}
			}
		}
	}

	/**Determines whether a move from (x1, y1, to (x2, y2) is legal.
	   @param x1 The horizontal component of the coordinates containing the
	   piece to be tested.
	   @param y1 The vertical component of the coordinates containing the
	   piece to be tested.
	   @param x2 The horizontal component of the coordinates indicating the
	   prospective move.
	   @param y2 The vertical component of the coordinates indicating the
	   prospective move.
	   @return True if the specified slide or jump is legal within the current rules.
	   False if otherwise.
	*/
	def isLegalMove(x1:Int, y1:Int, x2:Int, y2:Int): Boolean = {
		return (isLegalJump(x1, y1, x2, y2) || isLegalSlide(x1, y1, x2, y2))
	}

	/**Returns a List, possibly null, of coordinates that the next move
	   must select from. The coordinates are contained in java.awt.Point objects.
	   If this List contains Points, then one set of coordinates specified by
	   these Points must be used in the next move according to the current RuleSet,
	   and the move must be a jump. If the List is empty, the player
	   has free choice in which piece to move next.
	   @return A List, possibly empty, containing Point objects. Each Point object contains the coordinates of a piece on the board.
	*/
	 def mustJump: ArrayBuffer[Point] = {
		if (debug){
			println(" Checking for pieces which MUST jump...")
		}
		var tPieceList = new ArrayBuffer[Point]

		for (y<-1 to STD_BOARD_SIZE){		
			for (x<-1 to STD_BOARD_SIZE){		
				if ((isLight(x, y) && isLightPlayerTurn)
					|| (isDark(x, y) && isDarkPlayerTurn)) {
					if (canJump(x, y)){
						tPieceList.append(new Point(x, y))
					}
				}
			}
		}

		if (debug){
			println(
				" Must jump check complete: " + tPieceList + " must jump.")
		}
		return tPieceList
		}

	/**Returns the number of light pieces left in play.
	   @return The number of light pieces left on the board.
	 */
	def numberOfLightPieces: Int= {
		var tCount = 0
		for (y<-0 until STD_BOARD_SIZE){		
			for (x<-0 until STD_BOARD_SIZE){		
				if (iBoard(x)(y) == 1 || iBoard(x)(y) == 2)
					tCount = tCount + 1
			}
		}
		return tCount
	}

	/**Returns the number of dark pieces left in play.
	   @return The number of dark pieces left on the board.
	*/
	def numberOfDarkPieces: Int= {
		var tCount = 0
		for (y<-0 until STD_BOARD_SIZE){		
			for (x<-0 until STD_BOARD_SIZE){		
				if (iBoard(x)(y) == 3 || iBoard(x)(y) == 4)
					tCount = tCount + 1
			}
		}
		return tCount
	}

  
	def isSameColour(x1:Int, y1:Int, x2:Int, y2:Int): Boolean={
		if (isEmpty(x1, y1) || isEmpty(x2, y2)){
			return false;
		}
		return (
			(isLight(x1, y1) && isLight(x2, y2))
				|| (isDark(x1, y1) && isDark(x2, y2)));	}

	//Method for performing a slide. Makes no checks for legality.
	def slide(x1:Int, y1:Int, x2:Int, y2:Int)= {
		if (debug){
			println("Sliding...")
		}
		iBoard(x2 - 1)(y2 - 1) = iBoard(x1 - 1)(y1 - 1)
		iBoard(x1 - 1)(y1 - 1) = 0
	}

	//Private method for performing a jump. Makes no checks for legality.
	def jump(x1:Int, y1:Int, x2:Int, y2:Int) = {
		if (debug){
			println("Attempting to jump...")
		}
		iBoard(x2 - 1)(y2 - 1) = iBoard(x1 - 1)(y1 - 1)
		iBoard(x1 - 1)(y1 - 1) = 0

		//Locate the piece that has been jumped and remove it.
		val tTempX = x2 - x1
		val tTempY = y2 - y1
		//each value is either 2 or -2, indicating direction.
		if (tTempX == 2) {
			if (tTempY == 2) {
				iBoard(x1)(y1) = 0
			} else {
				iBoard(x1)(y1 - 2) = 0
			}
		}
		//Else -2:
		else {
			if (tTempY == 2) {
				iBoard(x1 - 2)(y1) = 0
			} else {
				iBoard(x1 - 2)(y1 - 2) = 0
			}
		}
	}

	def darkCanMove: Boolean = {
		for (y<-1 to STD_BOARD_SIZE){		
			for (x<-1 to STD_BOARD_SIZE){		
				if (isDark(x, y) && canMove(x, y))
					return true
			}
		}
		return false
	}
	
	def lightCanMove: Boolean= {
		for (y<-1 to STD_BOARD_SIZE){		
			for (x<-1 to STD_BOARD_SIZE){		
				if (isLight(x, y) && canMove(x, y))
					return true
			}
		}
		return false
	}

	/*True if the piece at the specified coordinate has been successfully crowned.
	 False if otherwise. Will only crown under correct board state conditions.*/
	def crown(x:Int, y:Int): Boolean= {
		try {
			if (isEmpty(x, y) || isKing(x, y) || isIllegalSpace(x, y)){
				return false
			}
			if (isDark(x, y) && y == STD_BOARD_SIZE) {
				iBoard(x - 1)(y - 1) = DARK_KING
				if (debug){
					println(" Crown Successful.")
				}
				return true
			}

			if (isLight(x, y) && y == 1) {
				iBoard(x - 1)(y - 1) = LIGHT_KING
				if (debug){
					println(" Crown Successful.")
				}
				return true
			}
			return false
		} catch {
			case e:Exception => return false
		}
	}

	class Point(xc: Int, yc: Int) {
	  var x: Int = xc
	  var y: Int = yc
	 
	  def getX(): Int = {
		  return xc
	  }
	  
	  def getY(): Int = {
		  return yc
	  }
	 override def toString(): String = "(" + x + ", " + y + ")"
	}
}